This is a starvation bug.
More details about this bug are at
POOL-146
JIRA page.
org.apache.commons.pool.impl.GenericObjectPool:
t1 t2 public Object borrowObject(Object key) throws Exception {
long starttime = System.currentTimeMillis();
1 10 Latch latch = new Latch(key);
...
// Add this request to the queue
2 11 _allocationQueue.add(latch);
// Work the allocation queue, allocating idle instances and
// instance creation permits in request arrival order
3 12 allocate();
}
...
7 17 if (null == latch.getPair()) {
...
switch(whenExhaustedAction) {
...
8 18 case WHEN_EXHAUSTED_BLOCK:
try {
synchronized (latch) {
if (maxWait <= 0) {
9 19 latch.wait();
...
}
private void allocate() {
...
for (;;) {
4 13 if (!_allocationQueue.isEmpty()) {
// First use any objects in the pool to clear the queue
5 14 Latch latch = (Latch) _allocationQueue.getFirst();
15 ObjectQueue pool = (ObjectQueue)(_poolMap.get(latch.getkey()));
if (null == pool) {
pool = new ObjectQueue();
_poolMap.put(latch.getkey(), pool);
_poolList.add(latch.getkey());
}
latch.setPool(pool);
6 16 if (!pool.queue.isEmpty()) {
...
}
...
}
Precondition: _maxActive=N. N objects have been borrowed from pool with key "A". But no objects are borrowed from pool with key "B". Exhausted action is set to block.
a) thread 1 borrows an object from pool with key "A". Latch A is created at 1 and added to allocation queue at 2. Now _allocationQueue has latch A at the head.
b) thread 1 is blocked at 9 according to the exhausted action.
c) thread 2 borrows an object from pool with key "B". Latch B is created at 10 and added into the rear of allocation queue at 11. Now _allocationQueue has latch A at head and latch B at rear.
d) thread 2 calls allocate at 12 and comes to 14 due to _allocationQueue is not empty. The head of _allocationQueue, which is latch A is fetched at 14.
e) pool with key "A" which is exhausted is fetched at 15. thread 2 is about to borrow object from pool "B", but latch B has no chance to be dealt until latch A is removed from _allocationQueue. So thread 2 is blocked at 19.
This bug is reproduced under pool 1.5 and JDK 1.6.0_33.
Execute the following scripts to run the test to reproduce the bug (assume the location of the pool test project is pool_test_home).
Linux:
${pool_test_home}/scripts/146.sh [--monitoroff]
Windows:
%pool_test_home%\scripts\146.bat [--monitoroff]
Example:
Use monitor to report and terminate the program when deadlock happens:
${pool_test_home}/scripts/146.sh
Turn off monitor:
${pool_test_home}/scripts/146.sh
--monitoroff
| Option | Function |
| --monitoroff, -mo | Turn off to stop reporting bug messages and ending program
when test runs into the expected concurrency bug which is a forever waiting. User has to terminate the program manually when this option is set. |